import { Link } from '@aws-amplify/ui-react';
import { FlutterAuthenticatorExample } from '@/components/FlutterAuthenticatorExample';
import { Example, ExampleCode } from '@/components/Example';

## Full UI Customization

In addition to customizing form fields and theming, you can also build a custom UI for one or more of the <Link isExternal href="https://pub.dev/documentation/amplify_authenticator/latest/amplify_authenticator/AuthenticatorStep.html">authenticator steps</Link> using a combination of prebuilt widgets from the amplify_authenticator package, and widgets that you build yourself. This can be used for simple use cases, such as adding a logo to the sign in screen, as well as more complex use cases.

This is done by providing an `authenticatorBuilder` argument to the Authenticator. If you are familiar with widgets like <Link isExternal href="https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html">StreamBuilder</Link>, <Link isExternal href="https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html">FutureBuilder</Link>, or <Link isExternal href="https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html">LayoutBuilder</Link>, this may feel familiar. `authenticatorBuilder` is a builder method that takes arguments for the current `BuildContext` and <Link isExternal href="https://pub.dev/documentation/amplify_authenticator/latest/amplify_authenticator/AuthenticatorState-class.html">AuthenticatorState</Link>. AuthenticatorState is a representation of the state being managed by the authenticator. It contains all the form field data (username, email, etc.), methods to perform authentication actions (sign in, sign up, etc.), and methods to transition between steps.

Below is an example of how you can use `authenticatorBuilder` to add a logo to both the sign up and sign in screen, as well as change the layout to replace the tab bar with a footer button.

This example uses several prebuilt widgets from the amplify_authenticator package, such as `SignInForm()`, `SignUpForm()`, `SignInFormField.username()`, and `SignInButton()`. All of the prebuilt widgets are integrated into the authenticator's state, meaning that you do not have to add an `onChanged` callback for the Form Fields, or an `onTap` callback for the Buttons. You can find a full list of the prebuilt forms, form fields, and buttons in <Link isExternal href="https://pub.dev/documentation/amplify_authenticator/latest/amplify_authenticator/amplify_authenticator-library.html">the API docs</Link>.

<ExampleCode>
  ```dart file=../../../../../../flutter/authenticator/lib/examples/full_ui_customization.dart
  ```
</ExampleCode>
  
<FlutterAuthenticatorExample
  id="flutter-authenticator-full-ui-customization"
  useCustomUI={true}
/>

### TOTP Setup

By utilizing the `authenticatorBuilder` argument, you can also customize the TOTP setup experience. We make available two particularly helpful widgets: `TotpSetupFormField.totpQrCode()` and `TotpSetupFormField.totpCopyKey()`. In the example below, examine how you could customize the setup screen by conditionally hiding the QR code on mobile platforms.

```dart{5}
@override
Widget build(BuildContext context) {
  // Check if the current platform is mobile. If it is, we will hide the QR code
  final isMobile = Theme.of(context).platform == TargetPlatform.iOS ||
      Theme.of(context).platform == TargetPlatform.android;

  return Authenticator(
    // `authenticatorBuilder` is used to customize the UI for one or more steps
    authenticatorBuilder: (BuildContext context, AuthenticatorState state) {
      switch (state.currentStep) {
        case AuthenticatorStep.continueSignInWithTotpSetup:
          return Scaffold(
            body: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                // Hide on mobile
                if (!isMobile) ...[
                  const Text(
                    'If you are on a mobile device, you can scan the QR code '
                    'using the Authenticator app.',
                  ),
                  // TOTP QR Code widget
                  TotpSetupFormField.totpQrCode(),
                  const SizedBox(height: 20),
                ],
                const Text('Copy the key below into your Authenticator app'),
                // TOTP copy key widget
                TotpSetupFormField.totpCopyKey(),
                const SizedBox(height: 20),
                FilledButton(
                  onPressed: () => state.changeStep(
                    AuthenticatorStep.confirmSignInWithTotpMfaCode,
                  ),
                  child: const Text('Continue'),
                ),
              ],
            ),
          );
        default:
          // Returning null defaults to the prebuilt authenticator for all other steps
          return null;
      }
    },
    child: MaterialApp(
      builder: Authenticator.builder(),
      home: const Scaffold(
        body: Center(
          child: Text('You are logged in!'),
        ),
      ),
    ),
  );
}
```
